package com.hivis.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hivis.entity.NotebookMsg;
import com.hivis.entity.SmsMsg;
import com.hivis.model.AjaxJson;
import com.hivis.model.PageJson;
import com.hivis.service.INotebookMsgService;
import com.hivis.service.ISmsMsgService;
import com.hivis.sms.GXYSender;
import com.hivis.sms.SmsResult;
import com.hivis.utils.StringUtils;
import com.hivis.websocket.MyWebSocketHandler;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.socket.BinaryMessage;
import org.springframework.web.socket.TextMessage;
import sun.misc.BASE64Encoder;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;

/**
 * 通知消息相关接口
 */
@Controller
@RequestMapping("/api/notify")
public class NotifyController {
    @Autowired
    private MyWebSocketHandler myWebSocketHandler;
    @Resource
    private INotebookMsgService notebookMsgService;
    @Resource
    private ISmsMsgService smsMsgService;
    @Resource(name = "taskExecutor")
    private TaskExecutor myThreadPool;

    // 接收新通知消息，推送外网终端（平板）
    @RequestMapping(value = "add", method = RequestMethod.POST)
    @ResponseBody
    public AjaxJson addNotify(String notebookId, String message, HttpServletRequest request, HttpServletResponse response) throws IOException {
        AjaxJson ajaxJson = new AjaxJson();
        request.setCharacterEncoding("UTF-8");
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
        NotebookMsg model = new NotebookMsg();
        model.setProductNo(notebookId);
        model.setContent(message);
        model.setCreateDate(new Date());

        // 是否有文件上传
        if (multipartResolver.isMultipart(request)) {
//            MultipartHttpServletRequest multiRequest = multipartResolver.resolveMultipart(request);
//            Iterator<String> iterator = multiRequest.getFileNames();
            MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
            Iterator<String> iterator = multiRequest.getFileNames();
            if (iterator.hasNext()) {
                MultipartFile file = multiRequest.getFile(iterator.next());
                System.out.println(file.getOriginalFilename());

                byte[] pictureData = file.getBytes();

                model.setVipPhoto(pictureData);
            }
        }

        try {
            notebookMsgService.addMessage(model); // 保存数据
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("messageId", model.getId());
            jsonObject.put("message", message);
            myWebSocketHandler.sendMessage(notebookId, new TextMessage(JSON.toJSONString(jsonObject))); // 通知平板端有数据
        }catch (Exception e){
            e.printStackTrace();
        }

        return ajaxJson;
    }

    // 发送手机短信信息
    @RequestMapping(value = "sms", method = RequestMethod.POST)
    @ResponseBody
    public AjaxJson sms(@RequestBody Map params, HttpServletRequest request, HttpServletResponse response) throws IOException {
        AjaxJson ajaxJson = new AjaxJson();
        String mobileStr = (String)params.get("mobiles");
        String mobiles2 = (String)null;
        final String content = (String)params.get("message");

        if(StringUtils.isNotEmpty(mobileStr)){
            myThreadPool.execute(new Runnable() {
                @Override
                public void run() {
                    SmsMsg smsMsg = new SmsMsg();
                    smsMsg.setPhone(mobileStr);
                    smsMsg.setContent(content);
                    smsMsg.setCreateDate(new Date());
                    try {
                        SmsResult smsResult = GXYSender.send(mobileStr, content);
                        if(smsResult == null){
                            smsMsg.setSendStatus("发送失败，网络连接失败");
                        } else if(smsResult.isSuccess()){
                            smsMsg.setSendStatus("发送成功");
                        }else {
                            smsMsg.setSendStatus("发送失败，" + smsResult.getMsg());
                        }
                    }catch (Exception e){
                        smsMsg.setSendStatus("发送失败，网络通讯异常");
                    }

                    smsMsgService.insert(smsMsg);
                }
            });
        }

        return ajaxJson;
    }

    // MultipartFile转BASE64字符串
    public static String multipartFileToBASE64(MultipartFile mFile) throws Exception{
        BASE64Encoder bEncoder=new BASE64Encoder();
        String[] suffixArra=mFile.getOriginalFilename().split("\\.");
        String preffix="data:image/jpg;base64,".replace("jpg", suffixArra[suffixArra.length - 1]);
        String base64EncoderImg=preffix + bEncoder.encode(mFile.getBytes()).replaceAll("[\\s*\t\n\r]", "");
        return base64EncoderImg;
    }

    // 接收新通知消息，推送外网终端（平板）
    @RequestMapping(value = "list", method = RequestMethod.GET, produces="text/json;charset=utf-8")
    @ResponseBody
    public String list(String notebookId, Integer messageId, int pageSize, int pageNo, HttpServletRequest request, HttpServletResponse response){
        Map<String, Object> params = new HashMap<>();
        params.put("productserial", notebookId);
        if(messageId != null)  params.put("messageId", messageId);
        int recordSize = notebookMsgService.selectCountByNotebooke(params); // 获取总条数

        params.put("currIndex", (pageNo-1)*pageSize);
        params.put("pageSize", pageSize);
        List<NotebookMsg> notebookMsgList = notebookMsgService.selectByNotebooke(params);
        PageJson<NotebookMsg> pageJson = new PageJson<>(pageNo, pageSize, recordSize, notebookMsgList);

        return JSON.toJSONString(pageJson);
    }

    /**
     * 根据指定大小压缩图片
     *
     * @param imageBytes  源图片字节数组
     * @param desFileSize 指定图片大小，单位kb
     * @return 压缩质量后的图片字节数组
     */
    public static void compressPicForScale(byte[] imageBytes, long desFileSize, double accuracy) throws IOException {
        ByteArrayInputStream bis = null;
        try {
            if (imageBytes == null || imageBytes.length <= 0 || imageBytes.length < desFileSize * 1024) {
                return;
            }
            while (imageBytes.length > desFileSize * 1024) {
                ByteArrayInputStream inputStream = null;
                ByteArrayOutputStream outputStream = null;
                try {
                    inputStream = new ByteArrayInputStream(imageBytes);
                    outputStream = new ByteArrayOutputStream(imageBytes.length);
                    Thumbnails.of(inputStream)
                            .scale(accuracy)
                            .outputQuality(accuracy)
                            .toOutputStream(outputStream);
                    imageBytes = outputStream.toByteArray();
                }finally {
                    inputStream.close();
                    outputStream.close();
                }
            }
//            bis = new ByteArrayInputStream(imageBytes);
//            Thumbnails.of(bis).scale(1f).toFile(descFile);
        }finally {
            bis.close();
        }
    }

    /**
     * 自动调节精度(经验数值)
     *
     * @param size 源图片大小
     * @return 图片压缩质量比
     */
    private static double getAccuracy(long size) {
        double accuracy;
        if (size < 900) {
            accuracy = 0.85;
        } else if (size < 2047) {
            accuracy = 0.6;
        } else if (size < 3275) {
            accuracy = 0.44;
        } else {
            accuracy = 0.4;
        }
        return accuracy;
    }
}
